package com.ksyun.ks3.services.handler;

import android.content.Context;
import android.util.Log;

import com.ksyun.ks3.exception.Ks3ClientException;
import com.ksyun.ks3.exception.Ks3ServiceException;
import com.ksyun.ks3.services.request.Ks3HttpRequest;
import com.ksyun.ks3.util.Constants;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.Response;

public abstract class FileAsyncHttpResponseHandler extends AsyncHttpResponseHandler {

    protected final File file;
    protected final boolean append;
    protected final boolean renameIfExists;
    Ks3HttpRequest request;

    public FileAsyncHttpResponseHandler(File file) {
        this(file, false);
    }

    public FileAsyncHttpResponseHandler(File file, boolean append) {
        this(file, append, false);
    }

    public FileAsyncHttpResponseHandler(File file, boolean append, boolean renameTargetFileIfExists) {
        this(file, append, renameTargetFileIfExists, false);
    }

    public FileAsyncHttpResponseHandler(File file, boolean append, boolean renameTargetFileIfExists, boolean usePoolThread) {
        this.file = file;
        this.append = append;
        this.renameIfExists = renameTargetFileIfExists;
    }

    public FileAsyncHttpResponseHandler(Context context) {
        this.file = this.getTemporaryFile(context);
        this.append = false;
        this.renameIfExists = false;
    }

    protected File getTemporaryFile(Context context) {
        try {
            return File.createTempFile("temp_", "_handled", context.getCacheDir());
        } catch (IOException var3) {
            Log.e(Constants.LOG_TAG, "Cannot create temporary file", var3);
            return null;
        }
    }

    @Override
    public void onFailure(Call call, IOException e) {
        if (!call.isCanceled()) {
            call.cancel();
        }
        e.printStackTrace();
        Log.e(Constants.LOG_TAG, e.toString());
    }

    public void onResponse(Call call, Response response) {
        Headers headers = response.headers();
        int code = response.code();
        try {
            if (code < 300 & code >= 200) {
                // 写流到文件中
                getResponseData(response);
                onSuccess(request, code, headers, null);
            } else {
                Ks3ServiceException serviceException = new Ks3ServiceException(code, headers, response.body().bytes());
                onFailure(request, null, serviceException);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(Constants.LOG_TAG, e.toString());
            if (call.isExecuted() && call.isCanceled()) {
                onCancel();
            } else {
                onFailure(request, new Ks3ClientException(e), null);
            }
        }
    }

    protected File getOriginalFile() {
        return this.file;
    }

    protected File getTargetFileByParsingURL(String requestURL) {
        String filename = requestURL.substring(requestURL.lastIndexOf(47) + 1, requestURL.length());
        File targetFileRtn = new File(this.getOriginalFile(), filename);
        if (targetFileRtn.exists() && this.renameIfExists) {
            String format;
            if (!filename.contains(".")) {
                format = filename + " (%d)";
            } else {
                format = filename.substring(0, filename.lastIndexOf(46)) + " (%d)" + filename.substring(filename.lastIndexOf(46), filename.length());
            }

            int index = 0;

            while (true) {
                targetFileRtn = new File(this.getOriginalFile(), String.format(format, index));
                if (!targetFileRtn.exists()) {
                    return targetFileRtn;
                }

                ++index;
            }
        } else {
            return targetFileRtn;
        }
    }

    protected byte[] getResponseData(Response entity) throws IOException {
        if (entity != null) {
            InputStream instream = entity.body().byteStream();
            FileOutputStream buffer = new FileOutputStream(this.file, this.append);
            if (instream != null) {
                try {
                    byte[] tmp = new byte[4096];
                    int count = 0;

                    int l;
                    while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) {
                        count += l;
                        buffer.write(tmp, 0, l);
                    }
                } catch (IOException e) {

                } finally {
                    buffer.flush();
                    buffer.close();
                }
            }
        }

        return null;
    }


    public abstract void onSuccess(Ks3HttpRequest request, int statusCode, Headers responseHeaders, byte[] response);

    public abstract void onFailure(Ks3HttpRequest request, Ks3ClientException clientException, Ks3ServiceException serviceException);

    public abstract void onRetry(int retryNo);

    public void onCancel() {
    }

    ;

    public void onProgress(long bytesWritten, long totalSize) {
    }


}
